package com.hyl.springbootsecurity.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

import static org.springframework.security.config.Customizer.withDefaults;

/**
 * SecurityConfig
 *
 * @author hyl
 * @date 2025-01-10
 */
@Configuration
@EnableWebSecurity
public class SecurityConfig {
    @Bean
    public PasswordEncoder getPw() {
        return new BCryptPasswordEncoder();
    }

    @Autowired
    private MyAccessDeniedHandler myAccessDeniedHandler;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http)
            throws Exception {
        //表单提交
        http.formLogin(formLoginSpec -> formLoginSpec
                .usernameParameter("username")
                .passwordParameter("password")
                // 自定义登录页面(SpringSecurity 默认的登录页面就会不显示)
                .loginPage("/tologin")
                // 设置提交登录请求的路径，不配置请求就进入不到 doLogin 所对应方法中，
                // 其值要求和 login.html 登录页面中表单的 action 值保持一致
                .loginProcessingUrl("/doLogin")
                // 配置登录成功后的跳转页面 (必须是 POST 请求)
//                .successForwardUrl("/toMain")
                .successHandler(new MyAuthenticationSuccessHandler("/toMain"))
//                .failureForwardUrl("/toError")
                .failureHandler(new MyAuthenticationFailureHandler("/toError"))
                .permitAll());


        // 授权认证
        // 设置除了登录页面，其他所有请求都必须被登录认证后才能进行访问。
        http.authorizeHttpRequests((authz) -> authz
                // 设置/tologin 不需要被认证 premitAll 允许任何人都可以访问
                .requestMatchers("/tologin").permitAll()
                .requestMatchers("/toError").permitAll()
                .requestMatchers("/css/**","js/**","images/**").permitAll()
                // anyRequest()为所有的请求， authenticated()表示登录认证后
                // 即所有请求都必须被登录认证后才能进行访问
                .anyRequest().authenticated()
        ).httpBasic(withDefaults());

        //权限
        http.exceptionHandling((ex) ->
               ex.accessDeniedHandler(myAccessDeniedHandler));

        // 关闭 csrf 防火墙
        http.csrf(AbstractHttpConfigurer::disable);
        return http.build();
    }

}
